package cn.shop.front.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.shop.base.UserInfoForSession;
import cn.shop.front.config.WeChatConfig;
import cn.shop.front.controller.wx.utils.Constants;
import cn.shop.front.entity.req.AppWxLogin;
import cn.shop.front.service.FrontUserService;
import cn.shop.transcation.frontUserModule.FrontUser;
import cn.shop.utils.ApiResult;
import cn.shop.utils.constant.Constant;
import cn.shop.utils.constant.SMSVerificationCode;
import cn.shop.validation.Save;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;

import static cn.shop.utils.ApiResult.fail;

/**
 * @author : 李一涵
 * @date : Created in 2022-7-23 10:41
 * @description :
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/frontUser")
public class RegisteController {

    @Resource
    private WeChatConfig weChatConfig;
    @Resource
    private FrontUserService frontUserService;

    /**
     * 新增数据
     *
     * @param frontUser 实体对象
     * @return 新增结果
     * @author jzw
     * @since 2022-01-07 15:45:19
     */
    @PostMapping("insert")
    public ApiResult<Map<String, Object>> insert(@Validated(Save.class) @RequestBody FrontUser frontUser) {
        String key = SMSVerificationCode.REGIST_KEY + frontUser.getPhone();
        SaSession session = SaSessionCustomUtil.getSessionById(key);
        Assert.notNull(session, "验证码已失效");
        String c = session.getString("code");
        if (StrUtil.isBlank(c) || !c.equals(frontUser.getCode())) {
            return fail("验证码不正确");
        }
        session.clear();
        boolean isSuccess = frontUserService.insert(frontUser);
        //注册成功后自动登录
        if (isSuccess) {
            Long frontUserId = frontUser.getId();
            StpUtil.login(frontUserId);
            String account = frontUser.getAccount();
            String name = frontUser.getName();
            StpUtil.getSession().set(Constant.USER, new UserInfoForSession(frontUserId, account, name));
            Dict dict = Dict.create();
            dict.set("token", StpUtil.getTokenValue()).set("name", name).set("account", account).set("balance", frontUser.getBalance());
            // 2023/3/21 更新最后登录时间
            frontUser.setLastLoginTime(DateUtil.toLocalDateTime(new Date()));
            frontUserService.updateById(frontUser);
            return ApiResult.success(dict);
        }
        //return ApiResult.result(isSuccess);
        return ApiResult.fail();
    }

    /**
     * 网站微信登陆
     */
    @GetMapping("/wxlogin")
    public ApiResult<Map<String, Object>> wxRegiste(String code, String state) {
        if (StrUtil.isBlank(code)) {
            return ApiResult.success();
        }
        JSONObject atObj = getAccessToken(code);
        String token = atObj.getStr("access_token");
        String unionid = atObj.getStr("unionid");
        String openid = atObj.getStr("openid");
        if (StrUtil.isBlank(token) || StrUtil.isBlank(unionid)) {
            return ApiResult.fail("微信扫码登录失败");
        }
        FrontUser wxuser = frontUserService.lambdaQuery()
                .eq(FrontUser::getUnionId, unionid)
                .one();
        if (wxuser == null) {
            JSONObject obj = getWechartInfo(token, openid);
            wxuser = frontUserService.wxuserCreate(obj.getStr("headimgurl"), unionid);
        }
        if (wxuser.getRisk()) {
            return fail("账号已被禁止登录，请联系客服");
        }
        FrontUser update = new FrontUser();
        update.setId(wxuser.getId());
        update.setAvatar(wxuser.getAvatar());
        // 2023/3/21 更新最后登录时间
        update.setLastLoginTime(DateUtil.toLocalDateTime(new Date()));
        frontUserService.updateById(update);
        Long frontUserId = wxuser.getId();
        StpUtil.login(frontUserId);
        String account = wxuser.getAccount();
        String name = wxuser.getName();
        StpUtil.getSession().set(Constant.USER, new UserInfoForSession(frontUserId, account, name));
        Dict dict = Dict.create();
        dict.set("token", StpUtil.getTokenValue()).set("name", name).set("account", account).set("balance", wxuser.getBalance());
        return ApiResult.success(dict);
    }

    /**
     * app微信登陆
     */
    @PostMapping("/applogin")
    public ApiResult<Map<String, Object>> applogin(@Validated @RequestBody AppWxLogin req) {
        FrontUser wxuser = frontUserService.lambdaQuery()
                .eq(FrontUser::getUnionId, req.getUnionid())
                .one();
        if (wxuser == null) {
            wxuser = frontUserService.wxuserCreate(req.getHeadimgurl(), req.getUnionid());
        }
        FrontUser update = new FrontUser();
        update.setId(wxuser.getId());
        update.setAvatar(wxuser.getAvatar());
        // 2023/3/21 更新最后登录时间
        update.setLastLoginTime(DateUtil.toLocalDateTime(new Date()));
        frontUserService.updateById(update);
        Long frontUserId = wxuser.getId();
        StpUtil.login(frontUserId);
        String account = wxuser.getAccount();
        String name = wxuser.getName();
        StpUtil.getSession().set(Constant.USER, new UserInfoForSession(frontUserId, account, name));
        Dict dict = Dict.create();
        dict.set("token", StpUtil.getTokenValue()).set("name", name).set("account", account).set("balance", wxuser.getBalance());
        return ApiResult.success(dict);
    }

    private JSONObject getAccessToken(String code) {
        String params = "?appid=" + weChatConfig.getLoginAppId() + "&secret=" + weChatConfig.getLoginAppSecret() + "&code=" + code + "&grant_type=authorization_code";
        String url = Constants.WX_ACCESS_TOKEN_URL;
        String res = HttpUtil.get(url + params);
        log.info("网站扫码登录获取 微信access_token : {}", res);
        return JSONUtil.parseObj(res);
    }

    private JSONObject getWechartInfo(String token, String openId) {
        String params = "?access_token=" + token + "&openid=" + openId + "&lang=zh_CN";
        String url = Constants.WX_USERINFO_URL;
        String res = HttpUtil.get(url + params);
        log.info("通过请求获取 微信用户信息 : {}", res);
        return JSONUtil.parseObj(res);
    }
}
